Nick Shek's Blog

Socket.io 1.3.5 cdn 同源問題

假設己經有一個HTTPS加密網站,為了令網站更快速。因此Socket.io使用了以下的javascript cdn :

<script src="https://cdn.socket.io/socket.io-1.3.4.js"></script>

但是socket.io server 會在 polling的請求回覆400 Bad request

解決方法是從Socket.io依賴的原始碼找出return Access-Control-Allow-Origin Header的地方,根據socket.io v1.3.5 的源始碼,return Access-Control-Allow-Origin Header的地方位於node_modules/socket.io/node_modules/engine.io/lib/transports/polling-xhr.js

/**
 * Returns headers for a response.
 *
 * @param {http.ServerRequest} request
 * @param {Object} extra headers
 * @api private
 */

XHR.prototype.headers = function(req, headers){
  headers = headers || {};

  if (req.headers.origin) {
    headers['Access-Control-Allow-Credentials'] = 'true';
    headers['Access-Control-Allow-Origin'] = req.headers.origin;
  } else {
    headers['Access-Control-Allow-Origin'] = '*';
  }

  this.emit('headers', headers);
  return headers;
};

將該function 改成

/**
 * Returns headers for a response.
 *
 * @param {http.ServerRequest} request
 * @param {Object} extra headers
 * @api private
 */

XHR.prototype.headers = function(req, headers){
  headers = headers || {};

  if (req.headers.origin) {
    headers['Access-Control-Allow-Credentials'] = 'true';
    if(req.headers.origin == "https://www.example-domain.com/"){
        headers['Access-Control-Allow-Origin'] = "https://cdn.socket.io/";
    }else{
        headers['Access-Control-Allow-Origin'] = req.headers.origin;
    }
  } else {
    headers['Access-Control-Allow-Origin'] = '*';
  }

  this.emit('headers', headers);
  return headers;
};

或者直接新增 headers['Access-Control-Allow-Origin'] = "https://cdn.socket.io/"; 雖然修改方法很醜。但至少可以令網站使用Socket.io CDN